﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using TcpTestServer.DataLayer;
using TcpTestServer.BusinessLogic;
using TcpTestServer.PresentationLayer;


namespace TcpTestServer
{
    public partial class ServerMainForm : Form
    {
        public ServerMainForm()
        {
            InitializeComponent();
         
            RobotXml = new XmlProtocol(12001, "UniversalRobot", ComponentType.robotArm);
            VisionXml = new XmlProtocol(12002, "VisionSystem", ComponentType.visionSystem);
            TaggingXml = new XmlProtocol(12003, "TaggingSystem", ComponentType.taggingSystem);

            RsdComponents.Add(RobotXml);
            RsdComponents.Add(VisionXml);
            RsdComponents.Add(TaggingXml);


            foreach (XmlProtocol Component in RsdComponents)
            {
                Component.ConnectionEvent += new ConnectionDel(ConnectionEvent);
                Component.MessageSent += new MessageCallbackDel(MessageSent);
                Component.ResponseReceived += new MessageCallbackDel(ResponseReceived);
            }
        
            //Control.CheckForIllegalCrossThreadCalls = false;
            trayIcon.Text = "RSD Controller Server";
            btnStartServer.Enabled = false;
            updateRobotTasksListbox();
        }

        private void ServerMainForm_Resize(object sender, System.EventArgs e)
        {
            if (FormWindowState.Minimized == WindowState)
                Hide();
        }

        private void notifyIcon1_DoubleClick(object sender,
                                     System.EventArgs e)
        {
            Show();
            WindowState = FormWindowState.Normal;
            this.Activate();
        }

        public void ConnectionEvent(object sender, ConnectionEventArgs args)
        {
            lock (this)
            {
                ClearTree();
                foreach (XmlProtocol component in RsdComponents)
                {
                    AddNode(component.Name, component.Description);
                    //AddChildNode(component.Name, component.ServiceName);
                    AddChildNode(component.Name, "TYPE:  " + component.Type);
                }
                ExpandTree();

                if (args.Status == ConnectionStatusEnum.connected)
                {
                    statusBox.Text += (TimeStamp() + "CONNECT: " + args.ComponentName + " @ " + args.Address);
                    statusBox.Text += Environment.NewLine;
                    AddChildNode(args.ComponentName, "CONNECTED @ " + args.Address);
                }
                else if (args.Status == ConnectionStatusEnum.server_set_up)
                {
                    statusBox.Text += (TimeStamp() + "STARTED: " + args.ComponentName + " server");
                    statusBox.Text += Environment.NewLine;

                }
                else if (args.Status == ConnectionStatusEnum.connection_error)
                {
                    statusBox.Text += (TimeStamp() + "Connection error : " + args.ErrorMessage);
                    statusBox.Text += Environment.NewLine;
                }

            }
        }

        public void ResponseReceived(object sender, MessageStatusArgs args)
        {
            ResponseMessageStatusArgs resp = (ResponseMessageStatusArgs)args;
            statusBox.Text += ("Response received to message " + args.MessageNr.ToString() + " : " + resp.Status.ToString());
            statusBox.Text += Environment.NewLine;

        }
        public void MessageSent(object sender, MessageStatusArgs args)
        {
            if (args.Status == MessageStatusEnum.successful)
            {
                statusBox.Text += ("Message sent " + (args.MessageNr).ToString());
                statusBox.Text += Environment.NewLine;
            }
            else
            {
                statusBox.Text += ("Message sending error");
                statusBox.Text += Environment.NewLine;
            }
            
        }


        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            stopServer();
            trayIcon.Visible = false;
            Application.Exit();
        }



        private void hide_Click(object sender, EventArgs e)
        {
                Hide();
        }

        private void quitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void stopToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void ServerMainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            stopServer();
            trayIcon.Visible = false;
        }

        private void btnStartServer_Click(object sender, EventArgs e)
        {
            startServer();
            btnStopServer.Enabled = true;
            btnStartServer.Enabled = false;
        }

        private void btnStopServer_Click(object sender, EventArgs e)
        {
            stopServer();
            btnStopServer.Enabled = false;
            btnStartServer.Enabled = true;
        }

        private void stopServer()
        {
            foreach (XmlProtocol Component in RsdComponents)
            {
                Component.TurnedOn = false;
            }
        }

        private void startServer()
        {
            foreach (XmlProtocol Component in RsdComponents)
            {
                Component.StartXmlThread();
            }
        }

        private void btnClearLog_Click(object sender, EventArgs e)
        {
            statusBox.Clear();
        }

        private void btnSentTestMessage_Click(object sender, EventArgs e)
        {

        }

         XmlProtocol RobotXml;
         XmlProtocol VisionXml ;
         XmlProtocol TaggingXml;
         List<XmlProtocol> RsdComponents = new List<XmlProtocol>();
         RsdStateMachine StateMachine = new RsdStateMachine();

         private void treeView_SERVICES_AfterSelect(object sender, TreeViewEventArgs e)
         {

         }
         delegate void AddNodeCallback(string key, string text);
         delegate void AddChildNodeCallback(string _parentKey, string text);
         delegate void ClearTreeCallback();
         delegate void ExpandTreeCallback();
         private void AddNode(string key, string text)
         {
             // InvokeRequired required compares the thread ID of the
             // calling thread to the thread ID of the creating thread.
             // If these threads are different, it returns true.
             if (this.treeView_SERVICES.InvokeRequired)
             {
                 AddNodeCallback d = new AddNodeCallback(AddNode);
                 this.Invoke(d, new object[] { key, text });
             }
             else
             {
                 this.treeView_SERVICES.Nodes.Add(key, text);
             }
         }
         private void ClearTree()
         {
             // InvokeRequired required compares the thread ID of the
             // calling thread to the thread ID of the creating thread.
             // If these threads are different, it returns true.
             if (this.treeView_SERVICES.InvokeRequired)
             {
                 ClearTreeCallback d = new ClearTreeCallback(ClearTree);
                 this.Invoke(d, new object[] { });
             }
             else
             {
                 this.treeView_SERVICES.Nodes.Clear();
             }
         }

         private void ExpandTree()
         {
             // InvokeRequired required compares the thread ID of the
             // calling thread to the thread ID of the creating thread.
             // If these threads are different, it returns true.
             if (this.treeView_SERVICES.InvokeRequired)
             {
                 ExpandTreeCallback d = new ExpandTreeCallback(ExpandTree);
                 this.Invoke(d, new object[] { });
             }
             else
             {
                 this.treeView_SERVICES.ExpandAll();
             }
         }

         private void AddChildNode(string _parentKey, string text)
         {
             // InvokeRequired required compares the thread ID of the
             // calling thread to the thread ID of the creating thread.
             // If these threads are different, it returns true.
             if (this.treeView_SERVICES.InvokeRequired)
             {
                 AddChildNodeCallback d = new AddChildNodeCallback(AddChildNode);
                 this.Invoke(d, new object[] { _parentKey, text });
             }
             else
             {
                 TreeNode[] parentNode = this.treeView_SERVICES.Nodes.Find(_parentKey, false);
                 if (parentNode != null && parentNode.Length > 0)
                     parentNode[0].Nodes.Add(text);
             }
         }

        private String TimeStamp(){
            return "[" + DateTime.Now.ToString("HH:mm:ss") + "] ";
        }

        private void sendTestMessage(XmlProtocol Component, String Command, List<Argument> output_arg_lst, List<Argument> reply_arg_lst)
        {
            lock (this)
            {
                if (Component.Connected && Component.IsReadyToSendMessage)
                {
                    int message_counter = 0;
                    DataLayer.Message m = new DataLayer.Message(Command, output_arg_lst, reply_arg_lst, message_counter++, 1000);
                    Component.MessageBuffer = m;
                }
            }
        }
        private void sendTestMessage(XmlProtocol Component)
        {
            List<Argument> output_arg_lst = new List<Argument>();
            List<Argument> reply_arg_lst = new List<Argument>();
            output_arg_lst.Add(new Argument("first", "1245", DataTypeEnum.integer));
            output_arg_lst.Add(new Argument("second", "aaaBBB", DataTypeEnum.text));
            output_arg_lst.Add(new Argument("third", "3.21", DataTypeEnum.floating_point));

            reply_arg_lst.Add(new Argument("first", DataTypeEnum.integer));
            reply_arg_lst.Add(new Argument("second", DataTypeEnum.text));
            String Command = "get_gripping_point";
            sendTestMessage(Component, Command, output_arg_lst, reply_arg_lst);

        }

        private void btn_TestMessageSend_Click(object sender, EventArgs e)
        {
            foreach (XmlProtocol protocol in RsdComponents)
                sendTestMessage(protocol);
        }

        private void btn_addRobotTask_Click(object sender, EventArgs e)
        {
            AddRobotTaskDialog dialog = new AddRobotTaskDialog();
            dialog.ShowDialog(this);
            updateRobotTasksListbox();
        }

        private void updateRobotTasksListbox()
        {
            lstBox_robotTasks.Items.Clear();
            List<String> tasks = StateMachine.getPendingTasks();
            foreach (String task in tasks)
                lstBox_robotTasks.Items.Add(task);
        }

        private void btn_clearRobotTask_Click(object sender, EventArgs e)
        {
            StateMachine.clearAllTasks();
            updateRobotTasksListbox();
        }

        private void btn_executeRobotTask_Click(object sender, EventArgs e)
        {
            StateMachine.executeNextTask();
        }

        private void btn_getObjectPose_Click(object sender, EventArgs e)
        {
            sendTestMessage(VisionXml);

        }



    }
}
